﻿using fuiou.Models;
using FuiouCode;
using FuiouPay;
using FuiouPay.Models.Request;
using FuiouPay.Models.Response;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using QRCoder;
using System;

namespace fuiou.Controllers {
    public class PayController : Controller {
        readonly ILogger logger;
        readonly string noPrefix = "1672";

        public PayController(ILogger<PayController> _logger, IOptions<FuiouPayInfo> _payInfo) {
            logger = _logger;

            if (_payInfo != null && _payInfo.Value != null) {
                Const.BaseUrl = _payInfo.Value.BaseUrl;
                Const.publicKey = _payInfo.Value.PublicKey;
                Const.privateKey = _payInfo.Value.PrivateKey;
                Const.ins_cd = _payInfo.Value.InsCd;
                Const.mchnt_cd = _payInfo.Value.MchntCd;
                noPrefix = _payInfo.Value.NoPrefix;
            }
        }

        public IActionResult Index() {
            return View();
        }

        public IActionResult Micropay(MicropayRequestInfo request) {
            try {
                Pay pay = new Pay();

                request.GoodsDes = "测试商品";
                request.MchntOrderNo = $"{noPrefix}{DateTime.Now:yyyyMMddHHmmss}{Utils.GetRandom(6)}";
                request.TxnBeginTs = DateTime.Now.ToString("yyyyMMddHHmmss");
                request.ReservedExpireMinute = 15;

                MicropayResponseInfo response = pay.Micropay(request);

                return Ok(new {
                    response,
                    orderNo = request.MchntOrderNo
                });
            } catch (Exception ex) {
                return Ok(new {
                    error = ex.Message, innerError = ex.InnerException != null ? ex.InnerException.Message : ""
                });
            }
        }

        public IActionResult PreCreate(PreCreateRequestInfo request) {
            try {
                Pay pay = new Pay();

                request.GoodsDes = "测试商品";
                request.MchntOrderNo = $"{noPrefix}{DateTime.Now:yyyyMMddHHmmss}{Utils.GetRandom(6)}";
                request.TxnBeginTs = DateTime.Now.ToString("yyyyMMddHHmmss");
                request.ReservedExpireMinute = 15;
                request.NotifyUrl = "http://fuioupay.styize.com/pay/notify";

                PreCreateResponseInfo response = pay.PreCreate(request);

                if ("000000".Equals(response.ResultCode)) {
                    QRCodeGenerator qrGenerator = new QRCodeGenerator();

                    QRCodeData qrCodeData = qrGenerator.CreateQrCode(response.QrCode, QRCodeGenerator.ECCLevel.Q);

                    Base64QRCode base64QRCode = new Base64QRCode(qrCodeData);

                    return Ok(new {
                        response,
                        base64 = base64QRCode.GetGraphic(35),
                        orderNo = request.MchntOrderNo
                    });
                }

                return Ok(response);
            } catch (Exception ex) {
                return Ok(new {
                    error = ex.Message, innerError = ex.InnerException != null ? ex.InnerException.Message : ""
                });
            }
        }

        public IActionResult Refund(RefundRequestInfo request) {
            try {
                Pay pay = new Pay();

                request.RefundOrderNo = $"{noPrefix}{DateTime.Now:yyyyMMddHHmmss}{Utils.GetRandom(6)}";

                RefundResponseInfo response = pay.Refund(request);

                return Ok(new {
                    response,
                    refundOrderNo = request.RefundOrderNo
                });
            } catch (Exception ex) {
                return Ok(new {
                    error = ex.Message, innerError = ex.InnerException != null ? ex.InnerException.Message : ""
                });
            }
        }

        public IActionResult CommonQuery(CommonQueryRequestInfo request) {
            try {
                Pay pay = new Pay();

                CommonQueryResponseInfo response = pay.CommonQuery(request);

                return Ok(new { response });
            } catch (Exception ex) {
                return Ok(new {
                    error = ex.Message, innerError = ex.InnerException != null ? ex.InnerException.Message : ""
                });
            }
        }

        public IActionResult CloseOrder(CloseOrderRequestInfo request) {
            try {
                Pay pay = new Pay();

                CloseOrderResponseInfo response = pay.CloseOrder(request);

                return Ok(new { response });
            } catch (Exception ex) {
                return Ok(new {
                    error = ex.Message, innerError = ex.InnerException != null ? ex.InnerException.Message : ""
                });
            }
        }

        public IActionResult CancelOrder(CancelOrderRequestInfo request) {
            try {
                Pay pay = new Pay();

                request.CancelOrderNo = $"{noPrefix}{DateTime.Now:yyyyMMddHHmmss}{Utils.GetRandom(6)}";

                CancelOrderResponseInfo response = pay.CancelOrder(request);

                return Ok(new { response });
            } catch (Exception ex) {
                return Ok(new {
                    error = ex.Message, innerError = ex.InnerException != null ? ex.InnerException.Message : ""
                });
            }
        }

        public IActionResult RefundQuery(RefundQueryRequestInfo request) {
            try {
                Pay pay = new Pay();

                RefundQueryResponseInfo response = pay.RefundQuery(request);

                return Ok(new { response });
            } catch (Exception ex) {
                return Ok(new {
                    error = ex.Message, innerError = ex.InnerException != null ? ex.InnerException.Message : ""
                });
            }
        }

        public IActionResult HisTradeQuery(HisTradeQueryRequestInfo request) {
            try {
                Pay pay = new Pay();

                HisTradeQueryResponseInfo response = pay.HisTradeQuery(request);

                return Ok(new { response });
            } catch (Exception ex) {
                return Ok(new { error = ex.Message, innerError = ex.InnerException != null ? ex.InnerException.Message : "" });
            }
        }

        public IActionResult WxPreCreate(WxPreCreateRequestInfo request) {
            try {
                Pay pay = new Pay();

                request.MchntOrderNo = $"{noPrefix}{DateTime.Now:yyyyMMddHHmmss}{Utils.GetRandom(6)}";
                request.GoodsDes = "测试商品";
                request.ProductId = "测试商品";
                request.TxnBeginTs = DateTime.Now.ToString("yyyyMMddHHmmss");
                request.ReservedExpireMinute = 15;
                request.NotifyUrl = "http://fuioupay.styize.com/pay/notify";

                WxPreCreateResponseInfo response = pay.WxPreCreate(request);

                return Ok(new { response, OrderNo = request.MchntOrderNo });
            } catch (Exception ex) {
                return Ok(new { error = ex.Message, innerError = ex.InnerException != null ? ex.InnerException.Message : "" });
            }
        }

        public IActionResult Notify(string req) {
            try {
                Pay pay = new Pay();

                logger.LogInformation($"Receive data from Fuiou : {req}");

                NotifyResponseInfo response = pay.Notify(req);

                logger.LogInformation(Newtonsoft.Json.JsonConvert.SerializeObject(response));

                ViewBag.Result = 1;
            } catch (Exception ex) {
                logger.LogError($"发生异常：" + ex.Message + (ex.InnerException != null ? "内部异常：" + ex.InnerException.Message : ""));
            }

            return View();
        }
    }
}
